import { IPSSysMap, IPSSysMapItem } from '@ibiz/dynamic-model-api';
import {
  AppMobMapProps,
  ICtrlEventParam,
  IMobMapCtrlController,
  MobChartEvents,
  MobMapCtrlController,
  ModelTool,
  Util,
} from 'ibz-core';
import { onMounted, reactive, ref, Ref, shallowReactive } from 'vue';
import { GenerateComponent } from '../component-base';
import { MDCtrlComponentBase } from './md-ctrl-component-base';
import { init, registerMap } from 'echarts';

/**
 * 移动端地图部件
 *
 * @export
 * @class AppMobMap
 * @extends MDCtrlComponentBase
 */
export class AppMobMap extends MDCtrlComponentBase<AppMobMapProps> {
  /**
   * 部件控制器
   *
   * @protected
   * @memberof AppMobMap
   */
  protected c!: IMobMapCtrlController;

  /**
   * 设置响应式
   *
   * @public
   * @memberof AppMobMap
   */
  setup() {
    this.c = shallowReactive<MobMapCtrlController>(this.getCtrlControllerByType('MAP') as MobMapCtrlController);
    super.setup();
  }

  /**
   * @description 部件初始化
   * @memberof AppMobMap
   */
  init() {
    super.init();
    this.initMapModel();
  }

  /**
   * @description 执行部件事件
   * @param {ICtrlEventParam} arg 事件参数
   * @memberof AppMobMap
   */
  public emitCtrlEvent(arg: ICtrlEventParam) {
    this.ctx.emit('ctrlEvent', arg);
    if (arg.action == 'onLoadSuccess') {
      this.items = arg.data;
      this.setAreaData();
      this.handleMapOptions();
      this.setOptions();
    }
  }

  /**
   * 地图div绑定的id
   *
   * @type {}
   * @memberof AppMobMap
   */
  public mapID: string = Util.createUUID();

  /**
   * 地图对象
   *
   * @type {*}
   * @memberof AppMobMap
   */
  public map: any;

  /**
   * 地图信息缓存
   *
   * @memberof AppMobMap
   */
  public addressCache: Map<string, any> = new Map();

  /**
   * 初始化配置
   *
   * @type {}
   * @memberof AppMobMap
   */
  public initOptions: any = {
    title: {
      text: '',
      left: 'center',
      top: 20,
    },
    tooltip: {
      trigger: 'item',
    },
    legend: {
      orient: 'vertical',
      x: 'left',
      y: 'center',
      data: [],
    },
    geo: {
      map: 'china',
      zoom: 1.2,
      label: {
        show: true,
        // 字体颜色
        color: 'rgba(0,0,0,0.7)',
      },
      itemStyle: {
        // 地图区域的颜色
        areaColor: '#e0ffff',
        // 边框颜色
        borderColor: 'rgba(0, 0, 0, 0.2)',
      },
      emphasis: {
        itemStyle: {
          areaColor: '#F3B329',
        },
      },
    },
    visualMap: [
      {
        min: 0,
        max: 1000,
        left: 'left',
        seriesIndex: 0,
        top: 'bottom',
        text: ['高', '低'],
        inRange: {
          color: ['#e0ffff', '#006edd'],
        },
        show: true,
      },
    ],
    series: [
      {
        name: '信息量',
        type: 'map',
        geoIndex: 0,
        coordinateSystem: 'geo',
        data: [],
        tooltip: {
          formatter: "<span style='margin-right: 20px'>{b}</span><b>{c}</b>",
        },
      },
    ],
  };

  /**
   * 显示的最大值
   *
   * @type {number}
   * @memberof AppMobMap
   */
  public valueMax: number = 0;

  /**
   * 显示图例
   *
   * @type {*}
   * @memberof AppMobMap
   */
  public showLegends: any[] = [];

  /**
   * 省份区域数据
   *
   * @memberof AppMobMap
   */
  public areaData: any = [];

  /**
   * 区域样式图数据
   *
   * @memberof AppMobMap
   */
  public regionData: any = [];

  /**
   * 地图数据
   *
   * @type {*}
   * @memberof AppMobMap
   */
  public items: Array<any> = [];

  /**
   * @description 是否打开上下文菜单
   * @type {*}
   * @memberof AppMobMap
   */
  public isShowContextMenu: boolean = true;

  /**
   * @description 长按定时器
   * @type {Ref<any>}
   * @memberof AppMobMap
   */
  public touchTimer: Ref<any> = ref(0);

  /**
   * @description 当前激活数据
   * @type {*}
   * @memberof AppMobMap
   */
  public activeData: any = reactive({});

  /**
   * @description 设置map大小
   * @memberof AppMobMap
   */
  public setMapSize() {
    if (App.isPreviewMode()) {
      const userParams: any = this.c.controlInstance.userParams || {};
      this.map.resize({
        width: userParams.height || 320,
        height: userParams.width || 575,
      });
    }
  }

  /**
   * @description 获取当前时间
   * @type {*}
   * @memberof AppMobMap
   */
  public getTimeNow() {
    return new Date().getTime();
  }

  /**
   * 地图点击事件
   *
   * @param data 选中数据
   * @memberof AppMobMap
   */
  public onClick(data: any[], event?: any) {
    this.c.selections = data;
    this.c.ctrlEvent(MobChartEvents.SELECT_CHANGE, this.c.selections);
  }

  /**
   * @description 长按开始
   * @param {*} data 节点数据
   * @param {*} event 事件源
   * @memberof AppMobMap
   */
  public onMouseDown(data: any, event: MouseEvent) {
    const timeStart = this.getTimeNow(); //获取鼠标按下时的时间
    this.touchTimer.value = setInterval(() => {
      const timeEnd = this.getTimeNow();
      if (timeEnd - timeStart > 1000) {
        this.activeData.value = {
          mouseEvent: event,
          data: data,
        };
        this.isShowContextMenu = true;
        this.clearTimer();
      }
    }, 100);
  }

  /**
   * @description 清除定时器
   * @memberof AppMobMap
   */
  public clearTimer() {
    clearInterval(this.touchTimer.value);
    this.touchTimer.value = 0;
  }

  /**
   * 注册
   *
   * @param name 地图名称
   * @memberof MobMapCtrlController
   */
  public registerMap() {
    // TODO地图不能配自定义参数，默认给中国地图
    // const userParams: any = this.c.controlInstance.userParams || {};
    // if (userParams?.mapName) {
    //   const geoJson = require(`../../../assets/json/map/${userParams?.mapName}.json`);
    //   registerMap(userParams?.mapName, geoJson);
    // } else {
    //   const geoJson = require(`../../../assets/json/map/china.json`);
    //   registerMap('china', geoJson);
    // }
  }

  /**
   * @description 部件挂载完成
   * @param {IParam} arg 事件参数
   * @memberof AppMobMap
   */
  public ctrlMounted(args?: any) {
    super.ctrlMounted(args);
    this.registerMap();
    const map: any = document.getElementById(this.mapID);
    if (map) {
      this.map = init(map);
    }
    if (this.map) {
      this.map.setOption(this.initOptions);
      this.setMapSize();
      // 如果是导航视图默认选中第一项
      this.map.on('selectchanged', 'series', (params: any) => {
        if (params.fromActionPayload?.custom) {
          const select: any[] = [params.fromActionPayload.custom];
          this.onClick(select);
        }
      });
      // 监听地图触发的点击事件
      this.map.on('click', 'series', (params: any) => {
        if (Object.is(params.seriesType, 'scatter') && params.data?.value) {
          const select: any[] = [params.data.value[3]];
          const event: any = params.event.event;
          this.onClick(select, event);
        } else if (
          (Object.is(params.seriesType, 'custom') || Object.is(params.seriesType, 'lines')) &&
          params.data?.coords
        ) {
          const selects: any[] = [];
          params.data.coords.forEach((coord: any) => {
            selects.push(coord[3]);
          });
          this.onClick(selects);
        }
      });
      // 监听地图触发的按下事件
      this.map.on('mousedown', 'series', (params: any) => {
        // 阻止浏览器默认行为
        params.event.event.preventDefault();
        if (Object.is(params.seriesType, 'scatter') && params.data?.value) {
          const select: any[] = [params.data.value[3]];
          const event: any = params.event.target;
          this.onMouseDown(select, event);
        }
      });
      // 监听地图触发的离开事件
      this.map.on('mouseup', 'series', (params: any) => {
        if (Object.is(params.seriesType, 'scatter') && params.data?.value) {
          this.clearTimer();
        }
      });
      // 图例改变过滤地图数据
      this.map.on('legendselectchanged', (params: any) => {
        if (params.name) {
          this.showLegends.forEach((showLegend: any) => {
            if (Object.is(showLegend.name, params.name)) {
              showLegend.show = !showLegend.show;
            }
          });
          // 重新设置地图数据
          this.valueMax = 0;
          const data = this.getAreaValueList();
          this.map.setOption({
            visualMap: {
              max: this.valueMax > 0 ? this.valueMax : 1000,
            },
            series: {
              data: data,
            },
          });
        }
      });
    }
  }

  /**
   * 初始化地图模型
   *
   * @memberof AppMobMap
   */
  public initMapModel() {
    const mapItems: IPSSysMapItem[] | null = this.c.controlInstance.getPSSysMapItems();
    this.showLegends = [];
    if (mapItems) {
      mapItems.forEach((item: IPSSysMapItem, index: number) => {
        this.showLegends.push({
          name: this.$tl(item.getNamePSLanguageRes()?.lanResTag, item.name),
          itemType: item.itemType?.toLowerCase(),
          show: true,
        });
        Object.assign(this.c.mapItems, {
          [item.itemType?.toLowerCase()]: {
            bkcolor: item.bKColor,
            color: item.color,
            borderColor: item.borderColor,
            borderWidth: item.borderWidth,
            content: item.getContentPSAppDEField()?.codeName.toLowerCase(),
            latitude: item.getLatitudePSAppDEField()?.codeName.toLowerCase(),
            longitude: item.getLongitudePSAppDEField()?.codeName.toLowerCase(),
            text: item.getTextPSAppDEField()?.codeName.toLowerCase(),
            tips: item.getTipsPSAppDEField()?.codeName.toLowerCase(),
            group: item.getGroupPSAppDEField()?.codeName.toLowerCase(),
            sort: item.getOrderValuePSAppDEField()?.codeName.toLowerCase(),
            code: index,
          },
        });
        this.initOptions.legend.data.push(item.name);
        this.initOptions.visualMap.push({
          type: 'piecewise',
          left: 'left',
          top: 'bottom',
          splitNumber: 1,
          seriesIndex: index + 1,
          pieces: [
            {
              label: item.name,
              min: index * 10,
              max: (index + 1) * 10,
              color: item.color,
              backgroundColor: item.bKColor,
              borderColor: item.borderColor,
              borderWidth: item.borderWidth,
            },
          ],
          show: false,
        });
        if (Object.is('POINT', item.itemStyle)) {
          this.initOptions.series.push({
            name: item.name,
            type: 'scatter',
            coordinateSystem: 'geo',
            itemType: item.itemType?.toLowerCase(),
            color: item.color,
            selectedMode: 'single',
            select: {
              itemStyle: {
                borderColor: item.borderColor,
                opacity: 1,
                borderWidth: 6,
              },
            },
            itemStyle: {
              color: item.bKColor,
              borderColor: item.borderColor,
              borderWidth: item.borderWidth,
            },
            geoIndex: 0,
            symbolSize: 16,
            label: {
              show: true,
              position: 'right',
              formatter: '{b}',
              color: item.color,
            },
            emphasis: {},
            encode: {
              value: 2,
            },
            // tooltip: {formatter: '{a}'},
            data: [],
          });
        } else if (Object.is('LINE', item.itemStyle)) {
          this.initOptions.series.push({
            name: item.name,
            type: 'lines',
            geoIndex: 0,
            itemType: item.itemType?.toLowerCase(),
            coordinateSystem: 'geo',
            polyline: true,
            tooltip: {
              show: true,
              formatter: (arg: any) => this.renderTooltip(arg),
            },
            lineStyle: {
              color: item.color,
              opacity: 1,
              width: 3,
            },
            data: [],
          });
        } else if (Object.is('REGION', item.itemStyle)) {
          this.initOptions.series.push({
            name: item.name,
            type: 'custom',
            geoIndex: 0,
            itemType: item.itemType?.toLowerCase(),
            coordinateSystem: 'geo',
            renderItem: (params: any, api: any) => this.renderRegion(params, api),
            selectedMode: 'single',
            itemStyle: {
              color: item.color,
              opacity: 0.5,
            },
            tooltip: {
              formatter: (arg: any) => this.renderTooltip(arg),
            },
            data: [],
          });
        }
      });
    }
  }

  /**
   * 更新大小
   *
   * @memberof AppMobMap
   */
  public updateSize() {
    if (this.map) {
      this.map.resize();
    }
  }

  /**
   * 设置地图数据(初始化)
   *
   * @memberof AppMobMap
   */
  public setAreaData() {
    const series: Array<any> = this.initOptions.series;
    if (!series || series.length == 0) {
      return;
    }
    this.valueMax = 0;
    this.initOptions.title.text = this.c.controlInstance?.logicName;
    this.initOptions.series[0].data = this.getAreaValueList();
    this.initOptions.visualMap[0].max = this.valueMax > 0 ? this.valueMax : 1000;
  }

  /**
   * 省份区域值集合
   *
   * @memberof AppMobMap
   */
  public getAreaValueList() {
    return [
      { name: '南海诸岛', value: this.calculateAreaValue('南海') },
      { name: '北京', value: this.calculateAreaValue('北京') },
      { name: '天津', value: this.calculateAreaValue('天津') },
      { name: '上海', value: this.calculateAreaValue('上海') },
      { name: '重庆', value: this.calculateAreaValue('重庆') },
      { name: '河北', value: this.calculateAreaValue('河北') },
      { name: '河南', value: this.calculateAreaValue('河南') },
      { name: '云南', value: this.calculateAreaValue('云南') },
      { name: '辽宁', value: this.calculateAreaValue('辽宁') },
      { name: '黑龙江', value: this.calculateAreaValue('黑龙江') },
      { name: '湖南', value: this.calculateAreaValue('湖南') },
      { name: '安徽', value: this.calculateAreaValue('安徽') },
      { name: '山东', value: this.calculateAreaValue('山东') },
      { name: '新疆', value: this.calculateAreaValue('新疆') },
      { name: '江苏', value: this.calculateAreaValue('江苏') },
      { name: '浙江', value: this.calculateAreaValue('浙江') },
      { name: '江西', value: this.calculateAreaValue('江西') },
      { name: '湖北', value: this.calculateAreaValue('湖北') },
      { name: '广西', value: this.calculateAreaValue('广西') },
      { name: '甘肃', value: this.calculateAreaValue('甘肃') },
      { name: '山西', value: this.calculateAreaValue('山西') },
      { name: '内蒙古', value: this.calculateAreaValue('内蒙古') },
      { name: '陕西', value: this.calculateAreaValue('陕西') },
      { name: '吉林', value: this.calculateAreaValue('吉林') },
      { name: '福建', value: this.calculateAreaValue('福建') },
      { name: '贵州', value: this.calculateAreaValue('贵州') },
      { name: '广东', value: this.calculateAreaValue('广东') },
      { name: '青海', value: this.calculateAreaValue('青海') },
      { name: '西藏', value: this.calculateAreaValue('西藏') },
      { name: '四川', value: this.calculateAreaValue('四川') },
      { name: '宁夏', value: this.calculateAreaValue('宁夏') },
      { name: '海南', value: this.calculateAreaValue('海南') },
      { name: '台湾', value: this.calculateAreaValue('台湾') },
      { name: '香港', value: this.calculateAreaValue('香港') },
      { name: '澳门', value: this.calculateAreaValue('澳门') },
    ];
  }

  /**
   * 计算省份区域数据
   *
   * @memberof AppMobMap
   */
  public async calculateAreaData() {
    this.areaData = [];
    if (this.items.length > 0) {
      for (const item of this.items) {
        const address: any = await this.getAddress(item.longitude, item.latitude);
        if (address) {
          const provinceName = address.province;
          this.areaData.push({
            name: provinceName,
            itemType: item.itemType,
            data: item,
          });
        }
      }
    }
  }

  /**
   * 调用服务，根据经纬度获取地址信息
   *
   * @param {*} lng 经度
   * @param {*} lat 纬度
   * @memberof AppMobMap
   */
  public async getAddress(lng: any, lat: any) {
    return new Promise((resolve, reject) => {
      let address: any = null;
      if (this.addressCache.get(lng + '-' + lat)) {
        address = this.addressCache.get(lng + '-' + lat);
        resolve(address);
      }
      // this.geocoder.getAddress([lng, lat], (status: any, result: any) => {
      //   if (status === 'complete' && result.info === 'OK') {
      //     if (result && result.regeocode) {
      //       address = result.regeocode.addressComponent;
      //       this.addressCache.set(lng + '-' + lat, address);
      //     }
      //   }
      //   resolve(address);
      // });
    });
  }

  /**
   * 计算省份区域数据值(项类容属性)
   *
   * @param name 省份区域名
   * @returns 省份区域值
   * @memberof AppMobMap
   */
  public calculateAreaValue(name: string) {
    const areaData: any = [];
    this.areaData.forEach((item: any) => {
      const showLegend = this.showLegends.find((_showLegend: any) => Object.is(_showLegend.itemType, item.itemType));
      if (item.name.indexOf(name) > -1 && showLegend?.show) {
        areaData.push(item.data);
      }
    });
    let value: number = 0;
    areaData.forEach((item: any) => {
      if (Number.isFinite(Number(item.content))) {
        value += item.content;
      } else {
        value += 1;
      }
    });
    this.valueMax = value > this.valueMax ? value : this.valueMax;
    return value;
  }

  /**
   * 配置整合
   *
   * @return {*}
   * @memberof AppMobMap
   */
  public handleMapOptions() {
    const series: Array<any> = this.initOptions.series;
    if (!series || series.length == 0) {
      return;
    }
    series.forEach((serie: any) => {
      const seriesData: Array<any> = [];
      this.items.forEach((item: any) => {
        if (Object.is(item.itemType, serie.itemType)) {
          seriesData.push(item);
        }
      });
      this.handleSeriesOptions(seriesData, serie);
    });
    Object.assign(this.initOptions.series, series);
  }

  /**
   * 整合序列数据
   *
   * @param {*} seriesData 序列数据
   * @param {*} serie 序列
   * @memberof AppMobMap
   */
  public handleSeriesOptions(seriesData: Array<any>, serie: any) {
    serie.id = serie.itemType;
    if (Object.is(serie.type, 'scatter')) {
      // 点样式数据处理
      seriesData.forEach((data: any) => {
        const tempItem = [parseFloat(data.longitude), parseFloat(data.latitude), data.content, data];
        const _data = {
          name: data.title,
          value: tempItem,
        };
        serie.data.push(_data);
      });
    } else if (Object.is(serie.type, 'lines') || Object.is(serie.type, 'custom')) {
      const groupDatas: Array<any> = [];
      // 获取对应分组的数据集合
      const getGroupItems = (groupName: any) => {
        const items: Array<any> = [];
        if (groupName) {
          seriesData.forEach((data: any) => {
            if (Object.is(data.group, groupName)) {
              items.push(data);
            }
          });
        }
        return items;
      };
      // 分组
      if (this.c.mapItems[serie.itemType].group) {
        seriesData.forEach((data: any) => {
          if (data.group) {
            const group = groupDatas.find((groupData: any) => Object.is(groupData.group, data.group));
            if (!group) {
              groupDatas.push({
                group: data.group,
                items: getGroupItems(data.group),
              });
            }
          }
        });
      } else {
        groupDatas.push({
          group: serie.name,
          items: seriesData,
        });
      }
      if (Object.is(serie.type, 'custom')) {
        // 区域图数据处理
        this.regionData = [];
      }
      groupDatas.forEach((groupData: any) => {
        if (this.c.mapItems[serie.itemType].sort) {
          groupData.items.sort((a: any, b: any) => {
            const x: any = a.sort;
            const y: any = b.sort;
            return x > y ? -1 : x < y ? 1 : 0;
          });
        }
        const coords: Array<any> = [];
        groupData.items.forEach((item: any) => {
          const coord: any[] = [parseFloat(item.longitude), parseFloat(item.latitude), item.content, item];
          coords.push(coord);
        });
        serie.data.push({
          name: groupData.group,
          coords: coords,
        });
      });
      if (Object.is(serie.type, 'custom')) {
        // 区域图数据处理
        this.regionData = [...serie.data];
      }
    }
  }

  /**
   * 设置配置
   *
   * @memberof AppMobMap
   */
  public setOptions() {
    if (!this.map) {
      return;
    }
    const options = Util.deepCopy(this.initOptions);
    this.map.setOption(options);
    // 如果是导航视图默认选中第一项
    if (this.c.isSelectFirstDefault) {
      const select: any = this.items.find((item: any) => Object.is(item.itemType, this.showLegends[0]?.itemType));
      this.map.dispatchAction({
        type: 'select',
        seriesId: this.showLegends[0]?.itemType,
        dataIndex: 0,
        custom: select,
      });
    }
    this.updateSize();
  }

  /**
   * 绘制悬浮提示
   *
   * @param arg
   */
  public renderTooltip(arg: any) {
    const curData: any = arg.data;
    const items: any[] = curData.coords;
    let content: any = '';
    if (Object.is('lines', arg.seriesType)) {
      content = items[0][2] + '-' + items[items.length - 1][2];
    } else {
      let total: number = 0;
      items.forEach((item: any) => {
        total += item[2];
      });
      content = total;
    }
    const interval: any = '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
    const tooltip = arg.name + '<br />' + arg.marker + curData.name + interval + content;
    return tooltip;
  }

  /**
   * 绘制区域图
   *
   * @param params 参数
   * @param api 方法集合
   * @returns
   */
  public renderRegion(params: any, api: any) {
    const children: any[] = [];
    const color = api.visual('color');
    this.regionData.forEach((data: any) => {
      const points: any[] = [];
      data.coords.forEach((value: any) => {
        points.push(api.coord(value));
      });
      const child: any = {
        type: 'polygon',
        shape: {
          points: points,
        },
        style: api.style({
          fill: color,
        }),
        select: {
          style: {
            opacity: 1,
            fill: color,
          },
        },
      };
      children.push(child);
    });
    return {
      type: 'group',
      children: children,
    };
  }

  /**
   * @description 绘制上下文菜单
   * @return {*}
   * @memberof AppMobMap
   */
  public renderContextMenu() {
    if (this.activeData.value) {
      const mouseEvent = this.activeData.value?.mouseEvent;
      const data = this.activeData.value?.data[0];
      const mapItem = (this.c.controlInstance as IPSSysMap)
        .getPSSysMapItems()
        ?.find((_mapItem: IPSSysMapItem) => Object.is(data.itemType.toLowerCase(), _mapItem.itemType.toLowerCase()));
      const contextMenu = ModelTool.findPSControlByName(
        mapItem?.getPSDEContextMenu?.()?.name as string,
        this.c.controlInstance.getPSControls(),
      );
      if (contextMenu && this.isShowContextMenu) {
        this.isShowContextMenu = false;
        const otherParams = {
          key: Util.createUUID(),
          navDatas: [data.curData],
          mouseEvent: mouseEvent,
          contextMenuActionModel: {},
        };
        return this.computeTargetCtrlData(contextMenu, otherParams);
      }
    }
  }

  /**
   * 多数据部件渲染
   *
   * @memberof AppMobMap
   */
  render() {
    if (!this.controlIsLoaded.value) {
      return null;
    }
    return (
      <div class={{ ...this.classNames }}>
        {this.renderPullDownRefresh()}
        <div style='height:auto'>{this.renderContextMenu()}</div>
        <div id={this.mapID} ref='map' class='map'></div>
      </div>
    );
  }
}

export const AppMobMapComponent = GenerateComponent(AppMobMap, Object.keys(new AppMobMapProps()));
